%YAML 1.2
---
# C#.sublime-syntax
#
#  Author:
#    Mike Krüger <mkrueger@novell.com>
#
#  Copyright (c) 2016 Microsoft Corporation
#  Copyright (c) 2007 Novell, Inc (http://www.novell.com)
#
#  Permission is hereby granted, free of charge, to any person obtaining a copy
#  of this software and associated documentation files (the "Software"), to deal
#  in the Software without restriction, including without limitation the rights
#  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
#  copies of the Software, and to permit persons to whom the Software is
#  furnished to do so, subject to the following conditions:
#
#  The above copyright notice and this permission notice shall be included in
#  all copies or substantial portions of the Software.
#
#  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
#  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
#  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
#  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
#  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
#  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
#  THE SOFTWARE.

name: "C#"
file_extensions:
  - cs
  - csx
scope: source.cs
contexts:
  main:
    - include: comments
    - include: keywords
    - include: numbers
    - include: strings
    - include: preprocessor
  comments:
    - match: '///'
      scope: comment.line.documentation.source.cs
      push:
        - match: '$\n?'
          pop: true
        - include: xmldoc
    - match: '//'
      scope: comment.line.source.cs
      push:
        - include: commenttags
        - match: $\n?
          pop: true
    - match: '/\*'
      scope: comment.block.source.cs
      push:
        - include: commenttags
        - match: '\*/\n?'
          pop: true
  commenttags:
    - match: '\b((?i:todo)|(?i:fixme)|(?i:hack)|(?i:undone))\b'
      scope: markup.other.source.cs
  xmldoc:
    - match: '(?x)(</?)((?:([-_[:alnum:]]+)(:))?([-_[:alnum:]]+))'
      captures:
        1: punctuation.definition.tag.source.cs
        2: entity.name.tag.source.cs
        3: entity.name.tag.namespace.source.cs
        4: punctuation.separator.colon.source.cs
        5: entity.name.tag.localname.source.cs
      push:
        - match: '(?x)(?:^|\s+)((?:([-_[:alnum:]]+)(:))?([-_[:alnum:]]+))(=)'
          captures:
            1: entity.other.attribute-name.source.cs
            2: entity.other.attribute-name.namespace.source.cs
            3: punctuation.separator.colon.source.cs
            4: entity.other.attribute-name.localname.source.cs
            5: punctuation.separator.equals.source.cs
        - match: '((/?>)|(?=($\n?)))'
          captures:
            1: punctuation.definition.tag.cs
          pop: true
        - match: "'"
          scope: string.quoted.single.source.cs
          push:
            - match: "('|(?=($\n?)))"
              pop: true
        - match: '"'
          scope: string.quoted.double.source.cs
          push:
            - match: '("|(?=($\n?)))'
              pop: true
    - match: $\n?
      pop: true
  keywords:
    - match: '@\w+\b'
    - match: '\b(this|base)\b'
      scope: keyword.other.access.source.cs
    - match: '\b(as|is|new|sizeof|typeof|stackalloc)\b'
      scope: keyword.operator.source.cs
    - match: '\b(else|if|switch|case|default)\b'
      scope: keyword.other.selection.source.cs
    - match: '\b(do|for|foreach|in|while)\b'
      scope: keyword.other.iteration.source.cs
    - match: '\b(break|continue|goto|return)\b'
      scope: keyword.other.jump.source.cs
    - match: '\b(yield|partial|global|where|__arglist|__makeref|__reftype|__refvalue|by|descending|from|group|into|orderby|select|let|ascending|join|on|equals)\b'
      scope: keyword.other.context.source.cs
    - match: '\b(try|throw|catch|finally)\b'
      scope: keyword.other.exception.source.cs
    - match: '\b(abstract|async|await|const|event|extern|override|readonly|sealed|static|virtual|volatile|public|protected|private|internal)\b'
      scope: keyword.other.modifiers.source.cs
    - match: '\b(bool|byte|char|decimal|double|float|int|long|sbyte|short|uint|ushort|ulong|object|string|var|dynamic)\b'
      scope: keyword.other.type.source.cs
    - match: '\b(void)\b'
      scope: keyword.other.void.source.cs
    - match: '\b(namespace|using)\b'
      scope: keyword.other.namespace.source.cs
    - match: '\b(get|set|add|remove|value)\b'
      scope: keyword.other.property.source.cs
    - match: '\b(class|interface|delegate|enum|struct)\b'
      scope: keyword.other.declaration.source.cs
    - match: '\b(params|ref|out)\b'
      scope: keyword.other.parameter.source.cs
    - match: '\b(explicit|implicit|operator)\b'
      scope: keyword.operator.declaration.source.cs
    - match: '\b(checked|unchecked|fixed|unsafe|lock)\b'
      scope: keyword.other.source.cs
    - match: '\b(true|false|null)\b'
      scope: constant.language.source.cs
  numbers:
    - match: '((\b\d+\.?\d+)|(\.\d+))([eE][+-]?\d*)?(F|f|D|d|M|m)?\b'
      scope: constant.numeric.float.source.cs
    - match: '\b\d+(([eE][+-]?\d*)?(F|f|D|d|M|m)|([eE][+-]?\d*))\b'
      scope: constant.numeric.float.source.cs
    - match: '\b0[bB][01_]+(U|u|L|l|UL|Ul|uL|ul|LU|Lu|lU|lu)?\b'
      scope: constant.numeric.binary.source.cs
    - match: '\b(0[xX][0-9a-fA-F]+?|\d+)(U|u|L|l|UL|Ul|uL|ul|LU|Lu|lU|lu)?\b'
      scope: constant.numeric.source.cs
  strings:
    - match: "'"
      scope: string.quoted.single.source.cs
      push:
        - match: '\\.'
          scope: constant.character.escape.source.cs
        - match: "('|$\n?)"
          pop: true
    - match: '@"'
      scope: string.quoted.other.verbatim.source.cs
      push:
        - match: '""'
          scope: constant.character.verbatim.escape.source.cs
        - match: '"'
          pop: true
    - match: '\$@"'
      scope: string.quoted.other.interpolated.verbatim.source.cs
      push:
        - match: '""'
          scope: constant.character.interpolated.verbatim.escape.source.cs
        - match: '"'
          pop: true
        - match: '\{\{'
        - match: '({)'
          captures:
            1: string.quoted.other.interpolated.verbatim.source.cs
          push:
            - meta_content_scope: source.cs
            - match: '(})'
              captures:
                1: string.quoted.other.interpolated.verbatim.source.cs
              pop: true
            - include: main
    - match: '\$"'
      scope: string.quoted.other.interpolated.source.cs
      push:
        - match: '\\.'
          scope: constant.character.escape.source.cs
        - match: '("|$\n?)'
          pop: true
        - match: '\{\{'
        - match: '({)'
          captures:
            1: string.quoted.other.interpolated.source.cs
          push:
            - meta_content_scope: source.cs
            - match: '(})'
              captures:
                1: string.quoted.other.interpolated.source.cs
              pop: true
            - include: main
    - match: '"'
      scope: string.quoted.double.source.cs
      push:
        - match: '\\.'
          scope: constant.character.escape.source.cs
        - match: '("|$\n?)'
          pop: true
  preprocessor:
    - match: '^\s*#(if|else|elif|endif|define|undef|warning|error|line|endregion|pragma)\b'
      scope: meta.preprocessor.source.cs
      push:
        - match: '\n?'
          pop: true
    - match: '^\s*(#region)(.*)$\n?'
      captures:
        1: meta.preprocessor.source.cs
        2: meta.preprocessor.region.name.source.cs
